package com.lingjtx.common.thread.pooling;

import com.lingjtx.common.core.constant.Const;
import com.lingjtx.common.core.constant.ServiceName;
import com.lingjtx.common.core.util.CommonUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
import reactor.netty.resources.LoopResources;

import java.time.Duration;

public class WebClientFactory implements ObjectFactory<WebClient> {

    private final ConnectionProvider connectionProvider;
    private final LoopResources loopResources;

    public WebClientFactory() {
        // 1. 自定义连接池（ConnectionProvider）
        this.connectionProvider = ConnectionProvider.builder("webclient-pool")
                .maxConnections(100)                 // 最大连接数
                .pendingAcquireTimeout(Duration.ofSeconds(60))  // 等待可用连接超时
                .build();
        // 2. 自定义 IO 线程池（EventLoopGroup）
        this.loopResources = LoopResources.create("webclient-nio-", 4, true);
    }

    @Override
    public WebClient create() {
        // 3. 创建 HttpClient 并绑定连接池和 IO 线程池
        HttpClient httpClient = HttpClient.create(connectionProvider)
                .runOn(loopResources)                // 设置线程池
                .responseTimeout(Duration.ofSeconds(10)) // 响应超时
                .compress(true);       // 开启 gzip

        String sign = CommonUtil.getBasicAuth(ServiceName.PROJECT, Const.MD5_SALT);
        return WebClient.builder()
                .baseUrl(Const.SERVER_URL)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .defaultHeader(Const.AuthTokenMap.AUTHORIZATION, sign)
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .build();
    }

    @Override
    public boolean validate(WebClient client) {
        return client != null;
    }

    @Override
    public void destroy(WebClient client) {
        shutdown();
    }

    @Override
    public void shutdown() {
        connectionProvider.dispose();
        loopResources.disposeLater().subscribe();
    }
}
